package com.huiminpay.merchant.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.domain.PageVO;
import com.huiminpay.common.cache.util.PhoneUtil;
import com.huiminpay.merchant.api.MerchantService;
import com.huiminpay.merchant.convert.MerchantCovert;
import com.huiminpay.merchant.convert.StaffConvert;
import com.huiminpay.merchant.convert.StoreConvert;
import com.huiminpay.merchant.dto.MerchantDTO;
import com.huiminpay.merchant.dto.StaffDTO;
import com.huiminpay.merchant.dto.StoreDTO;
import com.huiminpay.merchant.entity.Merchant;
import com.huiminpay.merchant.entity.Staff;
import com.huiminpay.merchant.entity.Store;
import com.huiminpay.merchant.entity.StoreStaff;
import com.huiminpay.merchant.mapper.MerchantMapper;
import com.huiminpay.merchant.mapper.StaffMapper;
import com.huiminpay.merchant.mapper.StoreMapper;
import com.huiminpay.merchant.mapper.StoreStaffMapper;
import com.huiminpay.user.api.TenantService;
import com.huiminpay.user.api.dto.tenant.CreateTenantRequestDTO;
import com.huiminpay.user.api.dto.tenant.TenantDTO;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 有点儿意思
 * @Description:
 */
@Service
public class MerchantServiceImpl implements MerchantService {

    @Autowired
    MerchantMapper merchantMapper;

    @Autowired
    StoreMapper storeMapper;

    @Autowired
    StaffMapper staffMapper;

    @Autowired
    StoreStaffMapper storeStaffMapper;

    @Reference
    TenantService tenantService;

    /**
     * 根据id查询商户信息
     *
     * @param merchantId 商户id
     * @return 封装的商户dto对象 作为service层传输的对象使用
     */
    @Override
    public MerchantDTO queryMerchantById(Long merchantId) {
        Merchant merchant = merchantMapper.selectById(merchantId);
        MerchantDTO merchantDTO = new MerchantDTO();
        BeanUtils.copyProperties(merchant,merchantDTO);
        return merchantDTO;
    }

    /**
     * 创建商户信息
     * @param merchantDTO 封装商户DTO对象
     * @return DTO信息
     */
    @Override
    public MerchantDTO createMerchant(MerchantDTO merchantDTO) {
        //校验 参数合法性
        if (merchantDTO == null ){
            throw new BusinessException(CommonErrorCode.E_300009);
        }
        //校验手机号
        if(StringUtils.isEmpty(merchantDTO.getMobile())){
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        //密码非空校验
        if (StringUtils.isEmpty(merchantDTO.getPassword())){
            throw new BusinessException(CommonErrorCode.E_100111);
        }
        //用户名非空校验
        if (StringUtils.isEmpty(merchantDTO.getUsername())){
            throw new BusinessException(CommonErrorCode.E_100110);
        }
        //校验手机号格式
        if (!PhoneUtil.isMatches(merchantDTO.getMobile())){
            throw new BusinessException(CommonErrorCode.E_100109);
        }
        // 根据手机号唯一性 查询商户表中是否存在 如果不存在则添加
        Integer count = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>().eq(Merchant::getMobile, merchantDTO.getMobile()));
        if (count >0){
            throw new BusinessException(CommonErrorCode.E_100113);
        }
        //调用SaaS平台 创建租户
        CreateTenantRequestDTO tenantRequestDTO = new CreateTenantRequestDTO();
        tenantRequestDTO.setMobile(merchantDTO.getMobile());
        tenantRequestDTO.setUsername(merchantDTO.getUsername());
        tenantRequestDTO.setPassword(merchantDTO.getPassword());
        tenantRequestDTO.setTenantTypeCode("huimin-merchant");
        tenantRequestDTO.setBundleCode("huimin-merchant");
        tenantRequestDTO.setName(merchantDTO.getUsername());
        TenantDTO tenantAndAccount = tenantService.createTenantAndAccount(tenantRequestDTO);

        Long tenantId = null;
        if (tenantAndAccount != null){
            tenantId = tenantAndAccount.getId();
        }
        //判断租户id是否存在  如果存在的话就不能再根据商户创建一个租户
        Integer num = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>().eq(Merchant::getTenantId, tenantId));
        if (num > 0){
            throw new BusinessException(CommonErrorCode.E_200017);
        }
        Merchant merchant = MerchantCovert.INSTANCE.dto2Entity(merchantDTO);
        merchant.setAuditStatus("0");
        //把租户id设置到商户表中
        merchant.setTenantId(tenantId);
        merchantMapper.insert(merchant);
        //新增商户下的门店信息
        //创建门店
        StoreDTO storeDTO = new StoreDTO();
        storeDTO.setMerchantId(merchant.getId());
        storeDTO.setStoreName("根门店");
        storeDTO.setParentId(0L);
        storeDTO.setStoreNumber(1L);
        storeDTO.setStoreStatus(true);
        StoreDTO store = this.createStore(storeDTO);
        //创建员工
        StaffDTO staffDTO = new StaffDTO();
        staffDTO.setMerchantId(merchant.getId());
        staffDTO.setMobile(merchantDTO.getMobile());
        staffDTO.setStaffStatus(true);
        staffDTO.setStoreId(store.getId());
        staffDTO.setUsername(merchantDTO.getUsername());
        StaffDTO staff = this.createStaff(staffDTO);
        //门店与员工绑定
        this.bindStaffToStore(staff.getId(), store.getId());
        return MerchantCovert.INSTANCE.entity2Dto(merchant);
    }

    /**
     * 请求保存资质信息 相当于更新数据库表操作
     * @param merchantId  商户id
     * @param merchantDTO 封装DTO对象
     */
    @Override
    public void applyMerchant(Long merchantId, MerchantDTO merchantDTO) {
        //校验参数
        if (merchantId == null || merchantDTO == null){
            throw new BusinessException(CommonErrorCode.E_300009);
        }
        //根据id查询商户
        Merchant merchant = merchantMapper.selectById(merchantId);
        if (merchant == null){
            throw new BusinessException(CommonErrorCode.E_200002);
        }
        //Dto转entity
        Merchant entity  = MerchantCovert.INSTANCE.dto2Entity(merchantDTO);
        //设置必要的参数
        entity.setId(merchantId);
        entity.setAuditStatus("1");
        entity.setMobile(merchant.getMobile());
        entity.setTenantId(merchant.getTenantId());
        merchantMapper.updateById(entity);
    }

    /**
     * 新增门店信息
     *
     * @param storeDTO 门店信息
     * @return 门店信息
     * @throws BusinessException
     */
    @Override
    public StoreDTO createStore(StoreDTO storeDTO) throws BusinessException {
        Store store = StoreConvert.INSTANCE.dto2entity(storeDTO);
        storeMapper.insert(store);
        return StoreConvert.INSTANCE.entity2dto(store);
    }

    /**
     * 新增门店员工信息
     * @param staffDTO 门店员工信息
     * @return 门店员工信息
     * @throws BusinessException
     */
    @Override
    public StaffDTO createStaff(StaffDTO staffDTO) throws BusinessException {
        //1.非空信息判断
        //1.1手机号非空判断
        if (StringUtils.isEmpty(staffDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        //1.2手机号格式判断
        if (!PhoneUtil.isMatches(staffDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100109);
        }
        //1.3手机号不能重复判断
        if (this.isExistMobile(staffDTO.getMerchantId(), staffDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100113);
        }
        //1.4用户名非空判断
        if (StringUtils.isEmpty(staffDTO.getUsername())) {
            throw new BusinessException(CommonErrorCode.E_100110);
        }
        //1.5用户名不能重复判断
        if (this.isExistUserName(staffDTO.getMerchantId(), staffDTO.getUsername())) {
            throw new BusinessException(CommonErrorCode.E_100114);
        }
        //2.插入数据
        Staff staff = StaffConvert.INSTANCE.dto2entity(staffDTO);
        staffMapper.insert(staff);
        return StaffConvert.INSTANCE.entity2dto(staff);
    }

    /**
     * 为 门店绑定员工
     * @param staffId 员工id
     * @param storeId 门店id
     * @throws BusinessException
     */
    @Override
    public void bindStaffToStore(Long staffId, Long storeId) throws BusinessException {
        StoreStaff storeStaff = new StoreStaff();
        storeStaff.setStaffId(staffId);
        storeStaff.setStoreId(storeId);
        storeStaffMapper.insert(storeStaff);
    }

    /**
     * 根据租户id查询商户
     *
     * @param tenantId 租户id
     * @return 商户
     */
    @Override
    public MerchantDTO queryMerchantByTenantId(Long tenantId) {
        Merchant merchant = merchantMapper.selectOne(new LambdaQueryWrapper<Merchant>().eq(Merchant::getTenantId, tenantId));
        if (merchant != null){
            return MerchantCovert.INSTANCE.entity2Dto(merchant);
        }
        return null;
    }

    /**
     * 分页查询商户下的门店信息
     *
     * @param storeDTO 门店信息
     * @param page     页码
     * @param limit    当前页数量
     * @return 分页对象
     */
    @Override
    public PageVO<StoreDTO> queryStoreByPage(StoreDTO storeDTO, Integer page, Integer limit) {
        //分页对象
        Page<Store> storePage = new Page<Store>(page, limit);
        //构造查询条件
        LambdaQueryWrapper<Store> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(storeDTO.getMerchantId()!=null, Store::getMerchantId,storeDTO.getMerchantId());
        //查询
        IPage<Store> storeIPage = storeMapper.selectPage(storePage, wrapper);
        List<Store> storePageRecords = storeIPage.getRecords();
        List<StoreDTO> storeDtoS = StoreConvert.INSTANCE.listentity2dto(storePageRecords);
        return new PageVO<StoreDTO>(storeDtoS,storeIPage.getTotal(),page,limit);
    }

    /**
     * 查询门店是否属于商户
     *
     * @param storeId    门店id
     * @param merchantId 商户id
     * @return 门店属于商户
     */
    @Override
    public Boolean queryStoreInMerchant(Long storeId, Long merchantId) {

        Integer count = storeMapper.selectCount(new LambdaQueryWrapper<Store>().eq(Store::getId, storeId)
                .eq(Store::getMerchantId, merchantId));
        return count > 0;
    }

    /**
     * 手机号不能重复判断
     * @param merchantId  商户id
     * @param phone 手机号
     * @return  否
     */
    private Boolean isExistMobile(Long merchantId,String phone){
        Integer count = staffMapper.selectCount(new LambdaQueryWrapper<Staff>().eq(Staff::getMerchantId, merchantId)
                .eq(Staff::getMobile, phone));
        return count > 0;
    }

    /**
     * 查询用户名不能重复
     * @param merchantId 商户id
     * @param userName 用户名
     * @return 否
     */
    private Boolean isExistUserName(Long merchantId, String userName){
        Integer count = staffMapper.selectCount(new LambdaQueryWrapper<Staff>().eq(Staff::getMerchantId, merchantId)
                .eq(Staff::getUsername, userName));
                return count > 0;
    }
}
